package cn.exrick.xboot.modules.graphics.serviceimpl;

import cn.exrick.xboot.common.constant.CommonConstant;
import cn.exrick.xboot.common.exception.ServiceException;
import cn.exrick.xboot.common.utils.SecurityUtil;
import cn.exrick.xboot.factory.MyBeanFactory;
import cn.exrick.xboot.factory.methodRequest.RequestFactory;
import cn.exrick.xboot.modules.graphics.dao.mapper.GraphicsPageMapper;
import cn.exrick.xboot.modules.graphics.entity.GraphicsContainer;
import cn.exrick.xboot.modules.graphics.entity.GraphicsPage;
import cn.exrick.xboot.modules.graphics.enums.GraphicsPageExceptionEnum;
import cn.exrick.xboot.modules.graphics.param.GraphicsPageParam;
import cn.exrick.xboot.modules.graphics.service.IGraphicsContainerService;
import cn.exrick.xboot.modules.graphics.service.IGraphicsPageService;
import cn.exrick.xboot.pojo.MethodRequest;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;

/**
 * 首页画布表接口实现
 * @author njp
 */
@Slf4j
@Service
@Transactional
public class IGraphicsPageServiceImpl extends ServiceImpl<GraphicsPageMapper, GraphicsPage> implements IGraphicsPageService {
@Autowired
private IGraphicsContainerService iGraphicsContainerService;
@Autowired
private SecurityUtil securityUtil;
    @Override
    public IPage<GraphicsPage> page(GraphicsPageParam graphicsPageParam, Page page,Boolean openDataFilter) {
        LambdaQueryWrapper<GraphicsPage> queryWrapper=new LambdaQueryWrapper<>();
        if(ObjectUtil.isNotNull(graphicsPageParam)){
            //根据标题模糊查询
            if(ObjectUtil.isNotEmpty(graphicsPageParam.getTitle())){
                queryWrapper.like(GraphicsPage::getTitle,graphicsPageParam.getTitle());
            }
            //根据组织id查询
            if(ObjectUtil.isNotEmpty(graphicsPageParam.getOrgId())){
                queryWrapper.eq(GraphicsPage::getOrgId,graphicsPageParam.getOrgId());
            }
            //todo 后续封装成统一方法（预采用函数式编程实现）
            if(openDataFilter){
            //获取权限
            List<String> depIds = securityUtil.getDeparmentIds();
                if (ObjectUtil.isEmpty(depIds)) {
                    return new Page<>();
                }else{
                    if(depIds!=null&&depIds.size()>0) {
                        queryWrapper.in(GraphicsPage::getOrgId, depIds);
                    }
                }
            }
            //查询未删除的
            queryWrapper.ne(GraphicsPage::getDelFlag, CommonConstant.DEL_FLAG);
        }
        IPage page1 = this.page(page, queryWrapper);
        return page1;
    }

    @Override
    public MethodRequest add(GraphicsPageParam graphicsPageParam) {
        this.checkParam(graphicsPageParam,1,false);
        MethodRequest methodRequest=null;
        //GraphicsPage graphicsPage=new GraphicsPage();
        MyBeanFactory myBeanFactory=MyBeanFactory.getMyBeanFactory();
        GraphicsPage graphicsPage = myBeanFactory.createBean(GraphicsPage.class);
        CopyOptions copyOptions = new CopyOptions();
        //设置拷贝时忽略null值
        copyOptions.setIgnoreNullValue(true);
        BeanUtil.copyProperties(graphicsPageParam, graphicsPage,copyOptions);
        boolean flag = this.save(graphicsPage);
        if(flag){
             methodRequest = new RequestFactory().buildRequest(graphicsPage, flag);
        }else {
             methodRequest = new RequestFactory().buildRequest(null, flag);
        }
        return methodRequest;
    }

    @Override
    public GraphicsPage detail(GraphicsPageParam graphicsPageParam) {
        LambdaQueryWrapper<GraphicsPage> queryWrapper=new LambdaQueryWrapper();
        queryWrapper.eq(GraphicsPage::getId,graphicsPageParam.getId());
        //查询未删除的
        queryWrapper.ne(GraphicsPage::getDelFlag, CommonConstant.DEL_FLAG);
        GraphicsPage g = this.getOne(queryWrapper);
        List<GraphicsContainer> layoutDetail = iGraphicsContainerService.getGraphicsContainerListByGraphicsId(graphicsPageParam.getId());
        if(g!=null) {
            g.setLayoutDetail(layoutDetail);
        }else{
            throw new ServiceException(GraphicsPageExceptionEnum.GRAPHICS_NOT_EXIST);
        }
        return g;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean edit(GraphicsPageParam graphicsPageParam) {
        this.checkParam(graphicsPageParam,0,false);
        GraphicsPage graphicsPage = this.queryGraphicsPage(graphicsPageParam);
        graphicsPage.setUpdateTime(new Date());
        CopyOptions copyOptions = new CopyOptions();
        //设置拷贝时忽略null值
        copyOptions.setIgnoreNullValue(true);
        BeanUtil.copyProperties(graphicsPageParam, graphicsPage,copyOptions);
        boolean flag = this.updateById(graphicsPage);
        return flag;
    }

    @Override
    public boolean delete(GraphicsPageParam graphicsPageParam) {
        this.checkParam(graphicsPageParam,0,false);
        GraphicsPage graphicsPage = this.queryGraphicsPage(graphicsPageParam);
        Integer delFlag = graphicsPage.getDelFlag();
        if(CommonConstant.DEL_FLAG.equals(delFlag)){
            throw new ServiceException(GraphicsPageExceptionEnum.GRAPHICS_CANNOT_DELETE);
        }else if(CommonConstant.GraphicsPage_STATUS_NORMAL.equals(graphicsPage.getStatus())){
            throw new ServiceException(GraphicsPageExceptionEnum.GRAPHICS_IS_USE_CANNOT_DELETE);
        }
        graphicsPage.setDelFlag(CommonConstant.DEL_FLAG);
        this.updateById(graphicsPage);
        iGraphicsContainerService.deleteByGraphicsId(graphicsPage.getId());
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveLayout(GraphicsPageParam graphicsPageParam) {
        //先保存界面基本信息(调用修改方法)
        this.edit(graphicsPageParam);
        //将详细的界面设计（界面与容器的对应关系和容器在界面中的布局）
         List<GraphicsContainer> layoutDetail = graphicsPageParam.getLayoutDetail();
        //先删除容器与界面对应关系数据
        iGraphicsContainerService.deleteByGraphicsId(graphicsPageParam.getId());
         //开始保存layoutDetail
        layoutDetail.forEach(gc ->{
            boolean add = iGraphicsContainerService.add(gc,graphicsPageParam.getId());
            if(!add){
                //删除失败,不管什么原因返回false都触发事务回滚
                throw new ServiceException(GraphicsPageExceptionEnum.GRAPHICS_CANNOT_ADD);
            }

        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void copyGraphicsPage(GraphicsPageParam graphicsPageParam) {
        //1.获取界面数据
        GraphicsPage graphicsPage = this.detail(graphicsPageParam);
        //更换组织id,去掉id属性
        graphicsPage.setOrgId(graphicsPageParam.getOrgId());
        //2.复制界面数据graphicsPage--->graphicsPageParam
        CopyOptions copyOptions = new CopyOptions();
        //设置拷贝时忽略null值
        copyOptions.setIgnoreNullValue(true);
        BeanUtil.copyProperties(graphicsPage, graphicsPageParam,copyOptions);
        graphicsPageParam.setId(null);
        //复制时将启用状态置为未启用状态
        graphicsPageParam.setStatus(CommonConstant.GraphicsPage_STATUS_DISABLE);
        //3.存储
        //存界面基本信息
        MethodRequest add = this.add(graphicsPageParam);
        GraphicsPage base = (GraphicsPage)add.getBase();
        //开始存储界面设计数据
        graphicsPageParam.setId(base.getId());
        this.saveLayout(graphicsPageParam);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void startGraphicsPage(GraphicsPageParam graphicsPageParam) {
        try {
            //查询当前界面获取其组织
            GraphicsPage graphicsPage = this.queryGraphicsPage(graphicsPageParam);
            String orgId = graphicsPage.getOrgId();
            //将该组织的界面状态都设置为未启用
            boolean b = this.editByOrgIdToStop(orgId);
            //将当前数据设置启用状态
            graphicsPage.setStatus(CommonConstant.GraphicsPage_STATUS_NORMAL);
            GraphicsPageParam gpp = new GraphicsPageParam();
            CopyOptions copyOptions = new CopyOptions();
            //设置拷贝时忽略null值
            copyOptions.setIgnoreNullValue(true);
            BeanUtil.copyProperties(graphicsPage, gpp, copyOptions);
            this.edit(gpp);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException(GraphicsPageExceptionEnum.GRAPHICS_CANNOT_EDIT_STATUS);
        }

    }

    @Override
    public GraphicsPage getGPbyOrgAndStatus(GraphicsPageParam graphicsPageParam) {
        this.checkParam(graphicsPageParam,2,true);
        LambdaQueryWrapper<GraphicsPage> queryWrapper=new LambdaQueryWrapper();
        queryWrapper.eq(GraphicsPage::getOrgId,graphicsPageParam.getOrgId());
        queryWrapper.eq(GraphicsPage::getStatus,CommonConstant.GraphicsPage_STATUS_NORMAL);
        //查询未删除的
        queryWrapper.ne(GraphicsPage::getDelFlag, CommonConstant.DEL_FLAG);
        GraphicsPage gp = this.getOne(queryWrapper);
        if(ObjectUtil.isEmpty(gp)){
            throw new ServiceException(GraphicsPageExceptionEnum.GRAPHICS_ORG_NOT_EXIST);
        }
        graphicsPageParam.setId(gp.getId());
        return this.detail(graphicsPageParam);
    }

    /**
     * 获取界面信息
     * @return
     */
    private GraphicsPage queryGraphicsPage(GraphicsPageParam graphicsPageParam){
        GraphicsPage g = this.getById(graphicsPageParam.getId());
        if (ObjectUtil.isNull(g)) {
            throw new ServiceException(GraphicsPageExceptionEnum.GRAPHICS_NOT_EXIST);
        }
        return g;
    }

    /**
     * 将某组织下的界面数据的启用状态都置为停止使用
     * @return
     */
    private boolean editByOrgIdToStop(String orgId){
        boolean flag=false;
        if(ObjectUtil.isNotEmpty(orgId)){
            LambdaUpdateWrapper<GraphicsPage> updateWrapper=new LambdaUpdateWrapper();
            updateWrapper.eq(GraphicsPage::getOrgId,orgId);
            updateWrapper.set(GraphicsPage::getStatus,CommonConstant.GraphicsPage_STATUS_DISABLE);
            flag=this.update(updateWrapper);
        }
    return flag;
    }
    /**
     * njp
     * 校验参数，判断状态是否正确
     */
    private void checkParam(GraphicsPageParam graphicsPageParam,int serviceType,boolean isExcludeSelf){
        //todo
        if(serviceType==1){
            //id不传值的校验
            if(ObjectUtil.isNotEmpty(graphicsPageParam.getId())){
                throw new ServiceException(GraphicsPageExceptionEnum.GRAPHICS_PARAM_ID);
            }
        }
    }
}